﻿using Microsoft.Extensions.Logging;
using SuperSocket.ProtoBase;
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GpsServer
{
    public class MyPipelineFilter : FixedHeaderPipelineFilter<MyPackageInfo>
    {
        protected static readonly Encoding Utf8Encoding = new UTF8Encoding();
        private readonly ILogger _logger;

        public MyPipelineFilter(ILogger logger, int headerSize) : base(headerSize)
        {
            _logger = logger;
        }

        protected override int GetBodyLengthFromHeader(ref ReadOnlySequence<byte> buffer)
        {
            var render = new SequenceReader<byte>(buffer);
            render.Advance(2);
            var b = render.TryRead(out byte len);
            var value = len + 2;//加上停止位
            return value;
        }

        protected override MyPackageInfo DecodePackage(ref ReadOnlySequence<byte> buffer)
        {
            _logger.LogDebug("Receive Data: {0}", Helper.ToHexStrFromByte(buffer.ToArray()));

            //校验停止位
            var a = buffer.Slice(buffer.Length - 2).ToArray()[0] == 0x0D;
            var b = buffer.Slice(buffer.Length - 1).ToArray()[0] == 0x0A;
            if (!a || !b) return null;

            //校验CRC
            var checkValue = buffer.Slice(buffer.Length - 4, 2).ToArray();
            var calcCheckValue = Helper.GetCrc16(buffer.Slice(2, buffer.Length - 6).ToArray());
            if (BitConverter.ToInt16(checkValue) != BitConverter.ToInt16(calcCheckValue)) return null;

            var package = new MyPackageInfo();
            var reader = new SequenceReader<byte>(buffer);

            //内容长度
            reader.Advance(2);
            reader.TryRead(out byte byteLen);
            var len = byteLen - 5;

            //Key协议号
            reader.TryRead(out byte byteProtocolNo);
            package.Key = (ProtocolNo)byteProtocolNo;

            //内容
            package.Content = reader.Sequence.Slice(4, len).ToArray();
            reader.Advance(len);

            //序号
            reader.TryReadBigEndian(out short serialNo);
            package.SerialNo = serialNo;

            return package;
        }
    }
}